package de.pa2.proxy.config;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;

import org.apache.commons.digester.Digester;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;

public class ServerConfiguration {
	private static final Logger LOG = LoggerFactory
			.getLogger(ServerConfiguration.class);
	public static String TAG = "server";
	private String fallback = "DIRECT";
	private int serverPort = 3127;
	private int proxyPort = 3128;
	private int deadEndPort = 3129;

	private ArrayList<HostConfiguration> hosts = new ArrayList<HostConfiguration>();

	public String getFallback() {
		return fallback;
	}

	public void setFallback(String fallback) {
		this.fallback = fallback;
	}

	public void addHostConfiguration(HostConfiguration host) {
		hosts.add(host);
	}

	public HostConfiguration[] getHostConfigurations() {
		return hosts.toArray(new HostConfiguration[] {});
	}

	public int getServerPort() {
		return serverPort;
	}

	public void setServerPort(int serverPort) {
		this.serverPort = serverPort;
	}

	public int getProxyPort() {
		return proxyPort;
	}

	public void setProxyPort(int proxyPort) {
		this.proxyPort = proxyPort;
	}

	public int getDeadEndPort() {
		return deadEndPort;
	}

	public void setDeadEndPort(int deadEndPort) {
		this.deadEndPort = deadEndPort;
	}

	public static ServerConfiguration parse(String xml) {
		ServerConfiguration result = null;

		Digester digester = new Digester();
		digester.setValidating(false); // ???

		// <server>
		digester.addObjectCreate(TAG, ServerConfiguration.class.getName());
		digester.addSetProperties(TAG);

		// <server><host>
		digester.addObjectCreate(TAG + "/" + HostConfiguration.TAG,
				HostConfiguration.class.getName());
		digester.addSetProperties(TAG + "/" + HostConfiguration.TAG);
		digester.addSetNext(TAG + "/" + HostConfiguration.TAG,
				"addHostConfiguration", HostConfiguration.class.getName());
		digester.addCallMethod(TAG + "/" + HostConfiguration.TAG + "/domain",
				"addDomain", 1);
		digester.addCallParam(TAG + "/" + HostConfiguration.TAG + "/domain", 0);
		digester.addCallMethod(TAG + "/" + HostConfiguration.TAG + "/url",
				"addUrl", 1);
		digester.addCallParam(TAG + "/" + HostConfiguration.TAG + "/url", 0);

		// <server><host><replacement>
		digester.addObjectCreate(TAG + "/" + HostConfiguration.TAG + "/"
				+ Replacement.TAG, Replacement.class.getName());
		digester.addSetProperties(TAG + "/" + HostConfiguration.TAG + "/"
				+ Replacement.TAG);

		digester.addCallMethod(TAG + "/" + HostConfiguration.TAG + "/"
				+ Replacement.TAG + "/lookup", "setLookup", 1);
		digester.addCallParam(TAG + "/" + HostConfiguration.TAG + "/"
				+ Replacement.TAG + "/lookup", 0);

		digester.addCallMethod(TAG + "/" + HostConfiguration.TAG + "/"
				+ Replacement.TAG, "setPattern", 1);
		digester.addCallParam(TAG + "/" + HostConfiguration.TAG + "/"
				+ Replacement.TAG + "/pattern", 0);

		digester.addCallMethod(TAG + "/" + HostConfiguration.TAG + "/"
				+ Replacement.TAG + "/urlPattern", "setUrlPattern", 1);
		digester.addCallParam(TAG + "/" + HostConfiguration.TAG + "/"
				+ Replacement.TAG + "/urlPattern", 0);

		digester.addCallMethod(TAG + "/" + HostConfiguration.TAG + "/"
				+ Replacement.TAG + "/replacement", "setReplacement", 1);
		digester.addCallParam(TAG + "/" + HostConfiguration.TAG + "/"
				+ Replacement.TAG + "/replacement", 0);

		digester.addSetNext(TAG + "/" + HostConfiguration.TAG + "/"
				+ Replacement.TAG, "addReplacement", Replacement.class
				.getName());
		try {
			result = (ServerConfiguration) digester
					.parse(new StringReader(xml));
		} catch (SAXException e) {
			LOG.error("could not read configuration; " + e.getMessage(), e);
		} catch (IOException e) {
			LOG.error("could not read configuration; " + e.getMessage(), e);
		}

		return result;
	}
}
